package batchprocessor;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class BatchParser {

    // Private Variables
    int num_commands;
    String wkdir;
    List<List<String>> commands;
    List<List<String>> file_list;

    public BatchParser(File file) throws ProcessException {
        try {
            
            // Create 2D List objects
            commands = new ArrayList<>();
            file_list = new ArrayList<>();
            
            // Reset the number of commands
            num_commands = 0;

            // Reset the Path
            wkdir = "";
     
            // Open the xml file
            FileInputStream fis = new FileInputStream(file);

            // Create Document containing XML elements
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(fis);

            // Get root node of Document and put children in the node list
            Element pnode = doc.getDocumentElement();
            NodeList nodes = pnode.getChildNodes();

            // Iterate through each node
            for (int idx = 0; idx < nodes.getLength(); idx++) {
                Node node = nodes.item(idx);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element elem = (Element) node;
                    parseCommand(elem);
                }
            }
        } catch (ParserConfigurationException | SAXException | IOException e) {
            System.out.println(e.getMessage());
        }
    }

    public int getNumCommands() {
        return commands.size();
    }
    
    public String getWkdir() {
        return wkdir;
    }

    // Need to make this a pointer
    public Command getCommand() {
        
        if (commands.isEmpty()) {
            return null;
        }
        
        Command command = new Command();
        
        // Set the command's id
        command.setId(commands.get(0).get(0));

        // Set the command's path
        command.setPath(commands.get(0).get(1));

        // Set the commands's args
        command.setCommands(commands.get(0).get(2));

        // Find the command's inFile
        for (List<String> inLine : file_list) {
            if (commands.get(0).get(3).equals(inLine.get(0))) {
                command.setInFile(inLine.get(1));
            }
        }

        // Find the command's outFile
        for (List<String> outLine : file_list) {
            if (commands.get(0).get(4).equals(outLine.get(0))) {
                command.setOutFile(outLine.get(1));
            }
        }
        
        // Remove this command
        commands.remove(0);
        return command;
    }

    // Check the element for the given attribute
    private String parseElement(Element elem, String attribute) 
        throws ProcessException {

        String temp;
        temp = elem.getAttribute(attribute);
        if ("".equals(temp)) {
            if(attribute.equals("id")){
                System.out.println("No command id");
                throw new ProcessException("No command id");
            }
            return "Null";
        } else {
            return temp;
        }
    }

    // Parse the attributes in the element
    private void parseCommand(Element elem) throws ProcessException {

        List<String> temp = new ArrayList<>();

        // Check the element name
        String cmdName = elem.getNodeName();

        if (cmdName == null) {
            System.out.println("Error processing element");
            throw new ProcessException("Error processing element");

        } else if ("wd".equalsIgnoreCase(cmdName)) {
            System.out.println("Parsing wd");
            wkdir = parseElement(elem, "path");

        } else if ("file".equalsIgnoreCase(cmdName)) {
            System.out.println("Parsing file");

            temp.add(parseElement(elem, "id"));
            temp.add(parseElement(elem, "path"));

            file_list.add(temp);

        } else if ("cmd".equalsIgnoreCase(cmdName)) {
            System.out.println("Parsing cmd");

            temp.add(parseElement(elem, "id"));
            temp.add(parseElement(elem, "path"));
            temp.add(parseElement(elem, "args"));
            temp.add(parseElement(elem, "in"));
            temp.add(parseElement(elem, "out"));

            commands.add(temp);

        } else if ("pipe".equalsIgnoreCase(cmdName)) {
            System.out.println("Parsing pipe");

        } else {
            System.out.println("Unknown Command");
            throw new ProcessException("Unknown Command");
        }
    }
}
